// PlainTextView.h : interface of the CPlainTextView class
//
/////////////////////////////////////////////////////////////////////////////

#if !defined(AFX_PlainTextView_H__053AD676_0AE2_11D6_8BF1_00500477589F__INCLUDED_)
#define AFX_PlainTextView_H__053AD676_0AE2_11D6_8BF1_00500477589F__INCLUDED_

#pragma once

typedef CWinTraits<WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_HSCROLL | WS_VSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE | ES_NOHIDESEL, WS_EX_CLIENTEDGE> CPlainTextViewWinTraits;

class CPlainTextView : public CWindowImpl<CPlainTextView, CEdit, CPlainTextViewWinTraits>,
					   public CEditCommands<CPlainTextView>
{
protected:
	typedef CPlainTextView thisClass;
	typedef CWindowImpl<CPlainTextView, CEdit, CPlainTextViewWinTraits> baseClass;

protected:
	HACCEL m_hAccel;
	WTL::CFont m_font;

public:
	CPlainTextView() :
		m_hAccel(NULL)
	{
	}

public:
	DECLARE_WND_SUPERCLASS(NULL, CEdit::GetWndClassName())

	BOOL PreTranslateMessage(MSG* pMsg)
	{
		if (pMsg)
		{
			if ((pMsg->hwnd == this->m_hWnd) || ::IsChild(this->m_hWnd, pMsg->hwnd))
			{
				// We'll have the Accelerator send the WM_COMMAND to our view
				if (m_hAccel != NULL && ::TranslateAccelerator(this->m_hWnd, this->m_hAccel, pMsg))
				{
					return TRUE;
				}
			}
		}
		return FALSE;
	}

	BEGIN_MSG_MAP(thisClass)
		MESSAGE_HANDLER(WM_CREATE, OnCreate)
		MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
		if (uMsg == WM_FORWARDMSG)
			if (PreTranslateMessage((LPMSG)lParam))
				return TRUE;
		CHAIN_MSG_MAP_ALT(CEditCommands<CPlainTextView>, 1)

		DEFAULT_REFLECTION_HANDLER()
	END_MSG_MAP()

	LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		// "base::OnCreate()"
		LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
		bHandled = TRUE;

		// "OnInitialUpdate"
		this->InitializeFont();
		this->CreateAccelerators();

		return lRet;
	}

	LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
	{
		this->DestroyAccelerators();

		bHandled = FALSE;
		return 0;
	}

	// Helpers
protected:
	void InitializeFont(void)
	{
		// Set the font of the edit control.
		CLogFont logFont;
		CClientDC dc(this->m_hWnd);
		logFont.SetHeight(8, dc);
		::lstrcpy(logFont.lfFaceName, _T("Courier New"));

		this->m_font.Attach(logFont.CreateFontIndirect());
		this->SetFont(m_font);

		// Set the tab stops to 4 characters.
		// Tab stops are in dialog units.
		TEXTMETRIC tm = {0};
		CFontHandle oldFont = dc.SelectFont(m_font);
		dc.GetTextMetrics(&tm);
		dc.SelectFont(oldFont);

		// Tab stops are in dialog units. We'll use a 4 character tab stop
		int dialogUnitsX = ::MulDiv(4, tm.tmAveCharWidth, LOWORD(GetDialogBaseUnits()));
		int tabStops = 4 * dialogUnitsX;

		this->SetTabStops(tabStops);
	}


	void CreateAccelerators(void)
	{
		const int cAccel = 13;
		ACCEL AccelTable[cAccel] = {
			{FVIRTKEY | FCONTROL | FNOINVERT, 'A', ID_EDIT_SELECT_ALL},
			{FVIRTKEY | FCONTROL | FNOINVERT, 'X', ID_EDIT_CUT},
			{FVIRTKEY | FCONTROL | FNOINVERT, 'C', ID_EDIT_COPY},
			{FVIRTKEY | FCONTROL | FNOINVERT, 'V', ID_EDIT_PASTE},
			{FVIRTKEY | FCONTROL | FNOINVERT, 'F', ID_EDIT_FIND},
			{FVIRTKEY | FNOINVERT, VK_F3, ID_EDIT_REPEAT},
			{FVIRTKEY | FSHIFT | FNOINVERT, VK_F3, ID_EDIT_REPEAT},
			{FVIRTKEY | FCONTROL | FNOINVERT, 'H', ID_EDIT_REPLACE},
			{FVIRTKEY | FCONTROL | FNOINVERT, 'Z', ID_EDIT_UNDO},
			{FVIRTKEY | FCONTROL | FNOINVERT, 'Y', ID_EDIT_REDO},
			// Don't do this one, DEL doesn't work right if its in here,
			// and the delete key works fine without it
			//{FVIRTKEY | FNOINVERT,             VK_DELETE,  ID_EDIT_CLEAR},
			{FVIRTKEY | FSHIFT | FNOINVERT, VK_DELETE, ID_EDIT_CUT},
			{FVIRTKEY | FCONTROL | FNOINVERT, VK_INSERT, ID_EDIT_COPY},
			{FVIRTKEY | FSHIFT | FNOINVERT, VK_INSERT, ID_EDIT_PASTE}};

		m_hAccel = ::CreateAcceleratorTable(AccelTable, cAccel);
	}

	void DestroyAccelerators(void)
	{
		if (m_hAccel)
		{
			::DestroyAcceleratorTable(m_hAccel);
			m_hAccel = NULL;
		}
	}
};


/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_PlainTextView_H__053AD676_0AE2_11D6_8BF1_00500477589F__INCLUDED_)
